<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Metadata 依赖关系查看器</title>
    <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            height: 100vh;
            overflow: hidden;
        }

        .container {
            display: flex;
            height: 100vh;
        }

        .sidebar {
            width: 350px;
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            border-right: 1px solid rgba(255, 255, 255, 0.2);
            display: flex;
            flex-direction: column;
            box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
        }

        .header {
            padding: 20px;
            background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            color: white;
            text-align: center;
        }

        .header h1 {
            font-size: 18px;
            margin-bottom: 5px;
        }

        .header p {
            font-size: 12px;
            opacity: 0.9;
        }

        .controls {
            padding: 20px;
            border-bottom: 1px solid #eee;
        }

        .search-box {
            width: 100%;
            padding: 10px;
            border: 2px solid #e0e0e0;
            border-radius: 25px;
            font-size: 14px;
            outline: none;
            transition: all 0.3s ease;
        }

        .search-box:focus {
            border-color: #4facfe;
            box-shadow: 0 0 10px rgba(79, 172, 254, 0.3);
        }

        .filter-section {
            margin-top: 15px;
        }

        .filter-title {
            font-size: 14px;
            font-weight: bold;
            margin-bottom: 10px;
            color: #333;
        }

        .filter-options {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
        }

        .filter-btn {
            padding: 6px 12px;
            border: 1px solid #ddd;
            border-radius: 15px;
            background: white;
            cursor: pointer;
            font-size: 12px;
            transition: all 0.3s ease;
        }

        .filter-btn.active {
            background: #4facfe;
            color: white;
            border-color: #4facfe;
        }

        .display-options {
            margin-top: 15px;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 8px;
        }

        .display-option {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

        .display-option input[type="checkbox"] {
            margin-right: 8px;
        }

        .display-option label {
            font-size: 13px;
            color: #555;
            cursor: pointer;
        }

        .stats {
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #eee;
        }

        .stat-item {
            display: flex;
            justify-content: space-between;
            margin-bottom: 8px;
            font-size: 13px;
        }

        .stat-label {
            color: #666;
        }

        .stat-value {
            font-weight: bold;
            color: #4facfe;
        }

        .node-details {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
        }

        .node-details h3 {
            color: #333;
            margin-bottom: 15px;
            font-size: 16px;
        }

        .detail-section {
            margin-bottom: 20px;
        }

        .detail-title {
            font-size: 14px;
            font-weight: bold;
            margin-bottom: 8px;
            color: #555;
        }

        .detail-content {
            background: #f8f9fa;
            padding: 10px;
            border-radius: 5px;
            font-size: 12px;
            line-height: 1.4;
        }

        .dependency-list {
            max-height: 150px;
            overflow-y: auto;
        }

        .dependency-item {
            padding: 5px 0;
            border-bottom: 1px solid #eee;
            cursor: pointer;
            transition: background 0.2s ease;
        }

        .dependency-item:hover {
            background: #e3f2fd;
        }

        .main-content {
            flex: 1;
            position: relative;
            background: #f5f5f5;
        }

        #network {
            width: 100%;
            height: 100%;
            background: #f5f5f5;
        }

        .loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            color: #666;
        }

        .loading-spinner {
            width: 40px;
            height: 40px;
            border: 4px solid #f3f3f3;
            border-top: 4px solid #4facfe;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin: 0 auto 10px;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .toolbar {
            position: absolute;
            top: 20px;
            right: 20px;
            z-index: 1000;
            display: flex;
            gap: 10px;
        }

        .toolbar-btn {
            padding: 10px 15px;
            background: white;
            border: 1px solid #ddd;
            border-radius: 5px;
            cursor: pointer;
            font-size: 12px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
            transition: all 0.3s ease;
        }

        .toolbar-btn:hover {
            background: #4facfe;
            color: white;
            border-color: #4facfe;
        }

        .no-selection {
            text-align: center;
            color: #999;
            font-style: italic;
            margin-top: 50px;
        }

        .status-bar {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 8px 15px;
            border-radius: 20px;
            font-size: 12px;
            z-index: 1000;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="sidebar">
            <div class="header">
                <h1>Metadata 依赖查看器</h1>
                <p>可视化JSON文件依赖关系</p>
            </div>
            
            <div class="controls">
                <input type="text" class="search-box" placeholder="搜索节点..." id="searchInput">
                
                <div class="filter-section">
                    <div class="filter-title">分类筛选</div>
                    <div class="filter-options" id="categoryFilters">
                        <div class="filter-btn active" data-category="all">全部</div>
                        <div class="filter-btn" data-category="bill">单据</div>
                        <div class="filter-btn" data-category="datamodel">数据模型</div>
                        <div class="filter-btn" data-category="approve">审批</div>
                        <div class="filter-btn" data-category="basedata">基础数据</div>
                        <div class="filter-btn" data-category="querysource">查询源</div>
                        <div class="filter-btn" data-category="queryview">查询视图</div>
                    </div>
                </div>

                <div class="display-options">
                    <div class="display-option">
                        <input type="checkbox" id="hideIsolated" checked>
                        <label for="hideIsolated">隐藏独立节点</label>
                    </div>
                    <div class="display-option">
                        <input type="checkbox" id="showLabels">
                        <label for="showLabels">显示节点标签</label>
                    </div>
                    <div class="display-option">
                        <input type="checkbox" id="useHierarchicalLayout">
                        <label for="useHierarchicalLayout">使用分层布局</label>
                    </div>
                    <div class="display-option">
                        <input type="range" id="nodeSize" min="5" max="30" value="8">
                        <label for="nodeSize">节点大小</label>
                    </div>
                </div>
            </div>
            
            <div class="stats">
                <div class="stat-item">
                    <span class="stat-label">总节点数:</span>
                    <span class="stat-value" id="totalNodes">0</span>
                </div>
                <div class="stat-item">
                    <span class="stat-label">总边数:</span>
                    <span class="stat-value" id="totalEdges">0</span>
                </div>
                <div class="stat-item">
                    <span class="stat-label">独立节点:</span>
                    <span class="stat-value" id="isolatedNodes">0</span>
                </div>
                <div class="stat-item">
                    <span class="stat-label">显示节点:</span>
                    <span class="stat-value" id="visibleNodes">0</span>
                </div>
                <div class="stat-item">
                    <span class="stat-label">选中节点:</span>
                    <span class="stat-value" id="selectedNode">无</span>
                </div>
            </div>
            
            <div class="node-details" id="nodeDetails">
                <div class="no-selection">点击节点查看详情</div>
            </div>
        </div>
        
        <div class="main-content">
            <div class="toolbar">
                <button class="toolbar-btn" onclick="fitNetwork()">适应画布</button>
                <button class="toolbar-btn" onclick="resetView()">重置视图</button>
                <button class="toolbar-btn" onclick="togglePhysics()">物理引擎</button>
                <button class="toolbar-btn" onclick="expandLayout()">展开布局</button>
                <button class="toolbar-btn" onclick="restoreAllNodes()" style="background: #ff6b6b; color: white;">恢复关系</button>
                <button class="toolbar-btn" onclick="switchVersion()" id="versionBtn" style="background: #9b59b6; color: white;">切换到过滤版本</button>
                <button class="toolbar-btn" onclick="reloadData()">重新加载</button>
            </div>
            
            <div id="network"></div>
            <div class="loading" id="loading">
                <div class="loading-spinner"></div>
                <div>正在加载依赖关系...</div>
            </div>
            
            <div class="status-bar" id="statusBar">
                准备就绪
            </div>
        </div>
    </div>

    <script>
        let network = null;
        let nodes = null;
        let edges = null;
        let allNodes = [];
        let allEdges = [];
        let selectedNodeId = null;
        let currentCategory = 'all';
        let hideIsolated = true;
        let showLabels = false;
        let useFilteredVersion = false;

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initializeNetwork();
            loadDependencyData();
            setupEventListeners();
        });

        // 设置事件监听器
        function setupEventListeners() {
            // 搜索功能
            document.getElementById('searchInput').addEventListener('input', function(e) {
                const query = e.target.value.toLowerCase();
                if (query.length > 0) {
                    searchNodes(query);
                } else {
                    showAllNodes();
                }
            });

            // 分类筛选
            document.querySelectorAll('.filter-btn').forEach(btn => {
                btn.addEventListener('click', function() {
                    document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
                    this.classList.add('active');
                    currentCategory = this.dataset.category;
                    updateDisplay();
                });
            });

            // 显示选项
            document.getElementById('hideIsolated').addEventListener('change', function(e) {
                hideIsolated = e.target.checked;
                updateDisplay();
            });

            document.getElementById('showLabels').addEventListener('change', function(e) {
                showLabels = e.target.checked;
                updateNetworkOptions();
            });

            document.getElementById('useHierarchicalLayout').addEventListener('change', function(e) {
                if (e.target.checked) {
                    expandLayout();
                }
            });

            document.getElementById('nodeSize').addEventListener('input', function(e) {
                const size = parseInt(e.target.value);
                network.setOptions({
                    nodes: {
                        size: size
                    }
                });
            });
        }

        // 初始化网络
        function initializeNetwork() {
            const container = document.getElementById('network');
            
            const options = {
                nodes: {
                    shape: 'dot',
                    size: 8,
                    font: {
                        size: 10,
                        color: '#333',
                        strokeWidth: 2,
                        strokeColor: '#ffffff'
                    },
                    borderWidth: 1,
                    shadow: false,
                    scaling: {
                        min: 5,
                        max: 20,
                        label: {
                            enabled: true,
                            min: 8,
                            max: 16,
                            maxVisible: 20
                        }
                    }
                },
                edges: {
                    width: 1,
                    color: { 
                        color: '#848484', 
                        highlight: '#4facfe',
                        hover: '#4facfe'
                    },
                    smooth: {
                        type: 'continuous',
                        roundness: 0.1
                    },
                    arrows: {
                        to: { 
                            enabled: true, 
                            scaleFactor: 0.5,
                            type: 'arrow'
                        }
                    },
                    scaling: {
                        min: 0.5,
                        max: 3
                    }
                },
                physics: {
                    enabled: true,
                    stabilization: { 
                        iterations: 200,
                        updateInterval: 50,
                        onlyDynamicEdges: false,
                        fit: true
                    },
                    barnesHut: {
                        gravitationalConstant: -8000,
                        centralGravity: 0.3,
                        springLength: 200,
                        springConstant: 0.04,
                        damping: 0.09,
                        avoidOverlap: 0.5
                    },
                    maxVelocity: 50,
                    minVelocity: 0.1,
                    solver: 'barnesHut',
                    timestep: 0.35,
                    adaptiveTimestep: true
                },
                interaction: {
                    hover: true,
                    selectConnectedEdges: false,
                    tooltipDelay: 200,
                    hideEdgesOnDrag: true,
                    hideNodesOnDrag: false
                },
                layout: {
                    improvedLayout: true,
                    clusterThreshold: 150
                }
            };

            network = new vis.Network(container, { nodes: [], edges: [] }, options);

            // 节点选择事件
            network.on('selectNode', function(params) {
                if (params.nodes.length > 0) {
                    selectedNodeId = params.nodes[0];
                    showNodeDetails(selectedNodeId);
                }
            });

            // 点击空白区域
            network.on('click', function(params) {
                if (params.nodes.length === 0) {
                    selectedNodeId = null;
                    showNodeDetails(null);
                }
            });

            // 网络稳定事件
            network.on('stabilizationIterationsDone', function() {
                updateStatusBar('网络已稳定');
            });
        }

        // 更新网络选项
        function updateNetworkOptions() {
            const options = {
                nodes: {
                    font: {
                        size: showLabels ? 12 : 0
                    }
                }
            };
            network.setOptions(options);
        }

        // 加载依赖数据
        async function loadDependencyData() {
            try {
                updateStatusBar('正在加载数据...');
                const response = await fetch('/api/dependencies');
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const data = await response.json();
                
                allNodes = data.nodes || [];
                allEdges = data.edges || [];
                
                updateDisplay();
                updateStats();
                hideLoading();
                updateStatusBar('数据加载完成');
            } catch (error) {
                console.error('加载数据失败:', error);
                updateStatusBar('数据加载失败: ' + error.message);
                hideLoading();
            }
        }

        // 更新显示
        function updateDisplay() {
            let filteredNodes = filterNodes(allNodes, currentCategory);
            
            // 如果启用隐藏独立节点
            if (hideIsolated) {
                filteredNodes = filterIsolatedNodes(filteredNodes, allEdges);
            }
            
            const filteredEdges = filterEdges(allEdges, filteredNodes);
            
            // 去重处理
            const uniqueNodes = [];
            const seenIds = new Set();
            
            filteredNodes.forEach(node => {
                if (!seenIds.has(node.id)) {
                    seenIds.add(node.id);
                    uniqueNodes.push({
                        id: node.id,
                        label: node.label,
                        group: node.group,
                        title: `${node.label}\n文件: ${node.file}\n分类: ${node.category}`,
                        color: getNodeColor(node.category),
                        // 添加位置信息以改善布局
                        x: Math.random() * 1000 - 500,
                        y: Math.random() * 1000 - 500
                    });
                }
            });
            
            const uniqueEdges = [];
            const seenEdges = new Set();
            
            filteredEdges.forEach((edge, index) => {
                const edgeKey = `${edge.from}-${edge.to}`;
                if (!seenEdges.has(edgeKey)) {
                    seenEdges.add(edgeKey);
                    uniqueEdges.push({
                        ...edge,
                        id: edge.id || `${edge.from}-${edge.to}-${index}`
                    });
                }
            });
            
            nodes = new vis.DataSet(uniqueNodes);
            edges = new vis.DataSet(uniqueEdges);
            
            network.setData({ nodes: nodes, edges: edges });
            
            // 更新统计信息
            document.getElementById('visibleNodes').textContent = uniqueNodes.length;
            
            // 延迟适应画布，让布局稳定
            setTimeout(() => {
                network.fit({ animation: true });
            }, 1000);
        }

        // 过滤独立节点
        function filterIsolatedNodes(nodes, edges) {
            const nodeIds = new Set(nodes.map(node => node.id));
            const connectedNodes = new Set();
            
            // 找出所有有连接的节点
            edges.forEach(edge => {
                if (nodeIds.has(edge.from) && nodeIds.has(edge.to)) {
                    connectedNodes.add(edge.from);
                    connectedNodes.add(edge.to);
                }
            });
            
            // 返回有连接的节点
            return nodes.filter(node => connectedNodes.has(node.id));
        }

        // 过滤节点
        function filterNodes(nodes, category) {
            if (category === 'all') return nodes;
            return nodes.filter(node => node.category === category);
        }

        // 过滤边
        function filterEdges(edges, filteredNodes) {
            const nodeIds = new Set(filteredNodes.map(node => node.id));
            return edges.filter(edge => 
                nodeIds.has(edge.from) && nodeIds.has(edge.to)
            );
        }

        // 获取节点颜色
        function getNodeColor(category) {
            const colors = {
                'bill': '#ff6b6b',
                'datamodel': '#4ecdc4',
                'approve': '#45b7d1',
                'basedata': '#96ceb4',
                'querysource': '#feca57',
                'queryview': '#ff9ff3',
                'print': '#54a0ff',
                'invoice': '#5f27cd',
                'message': '#00d2d3',
                'workflowQuery': '#ff9f43'
            };
            return colors[category] || '#95a5a6';
        }

        // 更新统计信息
        function updateStats() {
            document.getElementById('totalNodes').textContent = allNodes.length;
            document.getElementById('totalEdges').textContent = allEdges.length;
            
            // 计算独立节点数
            const connectedNodes = new Set();
            allEdges.forEach(edge => {
                connectedNodes.add(edge.from);
                connectedNodes.add(edge.to);
            });
            const isolatedCount = allNodes.length - connectedNodes.size;
            document.getElementById('isolatedNodes').textContent = isolatedCount;
        }

        // 更新状态栏
        function updateStatusBar(message) {
            document.getElementById('statusBar').textContent = message;
        }

        // 显示节点详情
        async function showNodeDetails(nodeId) {
            const detailsContainer = document.getElementById('nodeDetails');
            
            if (!nodeId) {
                detailsContainer.innerHTML = '<div class="no-selection">点击节点查看详情</div>';
                document.getElementById('selectedNode').textContent = '无';
                return;
            }

            try {
                const response = await fetch(`/api/node/${nodeId}`);
                const node = await response.json();
                
                document.getElementById('selectedNode').textContent = node.label;
                
                detailsContainer.innerHTML = `
                    <h3>${node.label}</h3>
                    
                    <div class="detail-section">
                        <div class="detail-title">操作选项</div>
                        <div class="detail-content">
                            <button class="action-btn" onclick="hideNodeDependents('${nodeId}')" style="background: #ff6b6b; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">
                                断开被依赖关系
                            </button>
                            <button class="action-btn" onclick="hideNodeDependencies('${nodeId}')" style="background: #4ecdc4; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">
                                断开依赖关系
                            </button>
                            <button class="action-btn" onclick="showOnlyNode('${nodeId}')" style="background: #feca57; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">
                                只显示此节点
                            </button>
                            <button class="action-btn" onclick="disconnectNodeLevels('${nodeId}')" style="background: #9b59b6; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 12px;">
                                断开层级关系
                            </button>
                        </div>
                    </div>
                    
                    <div class="detail-section">
                        <div class="detail-title">基本信息</div>
                        <div class="detail-content">
                            <strong>ID:</strong> ${node.id}<br>
                            <strong>文件:</strong> ${node.file}<br>
                            <strong>分类:</strong> ${node.category}<br>
                            <strong>定义:</strong> ${node.define || '无'}
                        </div>
                    </div>
                    
                    <div class="detail-section">
                        <div class="detail-title">依赖项 (${node.dependencies.length})</div>
                        <div class="detail-content dependency-list">
                            ${node.dependencies.length > 0 ? 
                                node.dependencies.map(dep => 
                                    `<div class="dependency-item" onclick="selectNode('${dep.id}')">${dep.label}</div>`
                                ).join('') : 
                                '<div style="color: #999; font-style: italic;">无依赖项</div>'
                            }
                        </div>
                    </div>
                    
                    <div class="detail-section">
                        <div class="detail-title">被依赖项 (${node.dependents.length})</div>
                        <div class="detail-content dependency-list">
                            ${node.dependents.length > 0 ? 
                                node.dependents.map(dep => 
                                    `<div class="dependency-item" onclick="selectNode('${dep.id}')">${dep.label}</div>`
                                ).join('') : 
                                '<div style="color: #999; font-style: italic;">无被依赖项</div>'
                            }
                        </div>
                    </div>
                `;
            } catch (error) {
                console.error('获取节点详情失败:', error);
                detailsContainer.innerHTML = '<div class="no-selection">获取详情失败</div>';
            }
        }

        // 选择节点
        function selectNode(nodeId) {
            network.selectNodes([nodeId]);
            network.focus(nodeId, { scale: 1.2, animation: true });
        }

        // 搜索节点
        function searchNodes(query) {
            const matchingNodes = allNodes.filter(node => 
                node.label.toLowerCase().includes(query) ||
                node.id.toLowerCase().includes(query) ||
                node.file.toLowerCase().includes(query)
            );
            
            if (matchingNodes.length > 0) {
                const nodeIds = matchingNodes.map(node => node.id);
                network.selectNodes(nodeIds);
                network.fit({ nodes: nodeIds });
            }
        }

        // 显示所有节点
        function showAllNodes() {
            network.unselectAll();
            selectedNodeId = null;
            showNodeDetails(null);
        }

        // 适应画布
        function fitNetwork() {
            network.fit({ animation: true });
        }

        // 重置视图
        function resetView() {
            network.setOptions({
                physics: { enabled: true }
            });
            network.fit({ animation: true });
        }

        // 切换物理引擎
        function togglePhysics() {
            const physicsEnabled = network.getOptions().physics.enabled;
            network.setOptions({
                physics: { enabled: !physicsEnabled }
            });
            updateStatusBar(physicsEnabled ? '物理引擎已关闭' : '物理引擎已开启');
        }

        // 展开布局
        function expandLayout() {
            updateStatusBar('正在展开布局...');
            
            // 使用分层布局算法
            const positions = calculateHierarchicalLayout(allNodes, allEdges);
            
            // 更新节点位置
            const nodeUpdates = [];
            positions.forEach((pos, nodeId) => {
                nodeUpdates.push({
                    id: nodeId,
                    x: pos.x * 2, // 放大间距
                    y: pos.y * 2,
                    fixed: false
                });
            });
            
            nodes.update(nodeUpdates);
            
            // 临时增加节点间距
            network.setOptions({
                physics: {
                    enabled: true,
                    barnesHut: {
                        gravitationalConstant: -12000,
                        centralGravity: 0.1,
                        springLength: 300,
                        springConstant: 0.02,
                        damping: 0.05,
                        avoidOverlap: 1.0
                    }
                }
            });
            
            // 适应画布
            setTimeout(() => {
                network.fit({ animation: true });
                updateStatusBar('布局展开完成');
            }, 1000);
        }

        // 计算分层布局
        function calculateHierarchicalLayout(nodes, edges) {
            const positions = new Map();
            const levels = new Map();
            const visited = new Set();
            
            // 找到所有没有依赖的根节点
            const rootNodes = nodes.filter(node => {
                return !edges.some(edge => edge.to === node.id);
            });
            
            // 从根节点开始分层
            let currentLevel = 0;
            let currentNodes = [...rootNodes];
            
            while (currentNodes.length > 0) {
                const nextLevelNodes = [];
                
                currentNodes.forEach((node, index) => {
                    if (!visited.has(node.id)) {
                        visited.add(node.id);
                        levels.set(node.id, currentLevel);
                        
                        // 计算水平位置
                        const x = (index - currentNodes.length / 2) * 200;
                        const y = currentLevel * 150;
                        
                        positions.set(node.id, { x, y });
                        
                        // 找到下一层的节点
                        const children = edges
                            .filter(edge => edge.from === node.id)
                            .map(edge => nodes.find(n => n.id === edge.to))
                            .filter(Boolean);
                        
                        nextLevelNodes.push(...children);
                    }
                });
                
                currentNodes = nextLevelNodes;
                currentLevel++;
            }
            
            // 处理剩余的孤立节点
            nodes.forEach(node => {
                if (!visited.has(node.id)) {
                    const x = Math.random() * 1000 - 500;
                    const y = Math.random() * 1000 - 500;
                    positions.set(node.id, { x, y });
                }
            });
            
            return positions;
        }

        // 重新加载数据
        async function reloadData() {
            showLoading();
            try {
                const response = await fetch('/api/reload', { method: 'POST' });
                const result = await response.json();
                
                if (result.count) {
                    await loadDependencyData();
                    updateStatusBar('数据重新加载完成');
                }
            } catch (error) {
                console.error('重新加载失败:', error);
                updateStatusBar('重新加载失败');
            }
        }

        // 切换数据版本
        async function switchVersion() {
            showLoading();
            try {
                const response = await fetch('/api/switch-version', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ useFiltered: !useFilteredVersion })
                });
                
                const result = await response.json();
                
                if (result.count) {
                    useFilteredVersion = !useFilteredVersion;
                    await loadDependencyData();
                    
                    // 更新按钮文本
                    const versionBtn = document.getElementById('versionBtn');
                    versionBtn.textContent = useFilteredVersion ? '切换到完整版本' : '切换到过滤版本';
                    
                    // 更新状态栏
                    let statusMessage = `已切换到${result.version}`;
                    if (result.filterInfo) {
                        statusMessage += ` (移除了 ${result.filterInfo.superNodeIds.length} 个超级节点)`;
                    }
                    updateStatusBar(statusMessage);
                }
            } catch (error) {
                console.error('切换版本失败:', error);
                updateStatusBar('切换版本失败');
            }
        }

        // 断开节点的被依赖关系
        function hideNodeDependents(nodeId) {
            updateStatusBar('正在断开被依赖关系...');
            
            // 找到所有指向该节点的边
            const edgesToRemove = allEdges.filter(edge => edge.to === nodeId);
            
            // 从allEdges中移除这些边
            allEdges.splice(0, allEdges.length, ...allEdges.filter(edge => edge.to !== nodeId));
            
            // 重新构建edges数据集
            const newEdges = allEdges.map((edge, index) => ({
                ...edge,
                id: edge.id || `${edge.from}-${edge.to}-${index}`
            }));
            
            // 更新edges数据集
            edges.clear();
            edges.add(newEdges);
            
            updateStatusBar(`已断开 ${edgesToRemove.length} 条被依赖关系`);
        }

        // 断开节点的依赖关系
        function hideNodeDependencies(nodeId) {
            updateStatusBar('正在断开依赖关系...');
            
            // 找到所有从该节点出发的边
            const edgesToRemove = allEdges.filter(edge => edge.from === nodeId);
            
            // 从allEdges中移除这些边
            allEdges.splice(0, allEdges.length, ...allEdges.filter(edge => edge.from !== nodeId));
            
            // 重新构建edges数据集
            const newEdges = allEdges.map((edge, index) => ({
                ...edge,
                id: edge.id || `${edge.from}-${edge.to}-${index}`
            }));
            
            // 更新edges数据集
            edges.clear();
            edges.add(newEdges);
            
            updateStatusBar(`已断开 ${edgesToRemove.length} 条依赖关系`);
        }

        // 只显示选中的节点
        function showOnlyNode(nodeId) {
            updateStatusBar('正在只显示选中节点...');
            
            // 隐藏所有其他节点
            const nodeUpdates = allNodes
                .filter(node => node.id !== nodeId)
                .map(node => ({
                    id: node.id,
                    hidden: true
                }));
            
            nodes.update(nodeUpdates);
            
            // 隐藏所有边
            const edgeUpdates = allEdges.map((edge, index) => ({
                id: edge.id || `${edge.from}-${edge.to}-${index}`,
                hidden: true
            }));
            
            edges.update(edgeUpdates);
            
            // 聚焦到选中的节点
            network.focus(nodeId, { scale: 2, animation: true });
            
            updateStatusBar('只显示选中节点');
        }

        // 断开节点的层级关系
        function disconnectNodeLevels(nodeId) {
            updateStatusBar('正在断开层级关系...');
            
            // 找到该节点的所有依赖和被依赖关系
            const outgoingEdges = allEdges.filter(edge => edge.from === nodeId);
            const incomingEdges = allEdges.filter(edge => edge.to === nodeId);
            const allRelatedEdges = [...outgoingEdges, ...incomingEdges];
            
            // 从allEdges中移除所有相关边
            allEdges.splice(0, allEdges.length, ...allEdges.filter(edge => 
                edge.from !== nodeId && edge.to !== nodeId
            ));
            
            // 重新构建edges数据集
            const newEdges = allEdges.map((edge, index) => ({
                ...edge,
                id: edge.id || `${edge.from}-${edge.to}-${index}`
            }));
            
            // 更新edges数据集
            edges.clear();
            edges.add(newEdges);
            
            updateStatusBar(`已断开 ${allRelatedEdges.length} 条层级关系`);
        }

        // 恢复所有断开的关系
        function restoreAllNodes() {
            updateStatusBar('正在恢复所有断开的关系...');
            
            // 重新加载原始数据
            loadDependencyData().then(() => {
                updateStatusBar('已恢复所有断开的关系');
            });
        }

        // 显示加载状态
        function showLoading() {
            document.getElementById('loading').style.display = 'block';
        }

        // 隐藏加载状态
        function hideLoading() {
            document.getElementById('loading').style.display = 'none';
        }
    </script>
</body>
</html>